// ----------------------------------------------------------------
//  Search - event handlers and bindings
// ----------------------------------------------------------------

/*
 * SearchBox initialization
 */
function initializeSearchBox() {
    $("#searchBox").keypress(function(event) {
        if (event.which == 13) {
            event.preventDefault();
            $("#searchBox").submit();
        }
    });

    $("#searchBox").submit(function(event) {
        var queryString = event.target.value;
        searchCountry(queryString);
    });

    $("#searchButton").click(function() {
        var queryString = $("#searchBox").val();
        searchCountry(queryString);
    });
}

// ----------------------------------------------------------------
//  Map
// ----------------------------------------------------------------

/*
 * Load map and place it at the top
 */
function prepareMap() {
    var options = {'valign':'top'};
    map.loadMap('/static/svg/world.svg', initializeMap, options);
}

/*
 * Map initialization
 */
function initializeMap() {
    var options = {
        styles: {
            fill: '#eee',
            cursor: "pointer"
        },
        key: "id",
        click: countryClick,
    };
    this.addLayer('countryLayer', options);
    //resizeMap();
}


/*
 * Map coloring
 */
function colorMap() {
	updateLegend();
	for (var id in _amounts) {
		color = getCountryColor(id);
				
		path = getPath(id);
		if (path) {
			highlightCountry(id, path, color);
		}
	}
}

// ----------------------------------------------------------------
//  Legend content
// ----------------------------------------------------------------

/*
 * Update legend according to current options
 */
function updateLegend() {
	MAX_PLUS_SUM = 0;
	MAX_MINUS_SUM = 0;
	for (var id in _amounts) {
		var amount = getIntervalAmount(id);
		if (amount > MAX_PLUS_SUM) {
			MAX_PLUS_SUM = amount;
		}
		if (amount < MAX_MINUS_SUM) {
			MAX_MINUS_SUM = amount;
		}
	}
	MIN_PLUS_SUM = MAX_PLUS_SUM;
	MIN_MINUS_SUM = MAX_MINUS_SUM;
	for (var id in _amounts) {
		var amount = getIntervalAmount(id);
		if (amount < MIN_PLUS_SUM && amount > 0) {
			MIN_PLUS_SUM = amount;
		}
		if (amount > MIN_MINUS_SUM && amount < 0) {
			MIN_MINUS_SUM = amount;
		}
	}
	
	if (_perCapita) {
		num = Math.floor(255 - (Math.log(Math.abs(MIN_PLUS_SUM))) * 28);
	} else {
		num = Math.floor(255 - (Math.log(Math.abs(MIN_PLUS_SUM)) - 14) * 28 + 50);
	}
	if (num > 200) {
		num = 200;
	}
	
	if (_perCapita) {
		num2 = Math.floor(255 - (Math.log(Math.abs(MAX_PLUS_SUM))) * 28);
	} else {
		num2 = Math.floor(255 - (Math.log(Math.abs(MAX_PLUS_SUM)) - 14) * 28 + 50);
	}
	if (num2 > 200) {
		num2 = 200;
	}
	c1 = toHex(13, num2, 0);
	c2 = toHex(13, num, 0);
	c3 = toHex(255, num, num);
	c4 = toHex(255, num2, num2);
	
	content = '<table>';	
	content += '<tr>';
	if (MAX_MINUS_SUM < 0) {
		content += '<td rowspan="4" style="background:-webkit-linear-gradient(top, ' +  c1 + ' 0%, ' +  c2 + ' 50%, ' +  c3 + ' 75%, ' +  c4 + ' 100%);';
		content += 'background:linear-gradient(top, ' +  c1 + ' 0%, ' +  c2 + ' 50%, ' +  c3 + ' 75%, ' +  c4 + ' 100%);';
		content += 'background:-moz-linear-gradient(top, ' +  c1 + ' 0%, ' +  c2 + ' 50%, ' +  c3 + ' 75%, ' +  c4 + ' 100%);';
		content += 'background:-o-linear-gradient(top, ' +  c1 + ' 0%, ' +  c2 + ' 50%, ' +  c3 + ' 75%, ' +  c4 + ' 100%);';
		content += 'background:-ms-linear-gradient(top, ' +  c1 + ' 0%, ' +  c2 + ' 50%, ' +  c3 + ' 75%, ' +  c4 + ' 100%);';
		content += ' height:200px; width:50px;"></td>';
	} else {
		content += '<td rowspan="4" style="background:-webkit-linear-gradient(top, ' +  c1 + ' 50%, ' +  c2 + ' 100%);';
		content += 'background:linear-gradient(top, ' +  c1 + ' 50%, ' +  c2 + ' 100%);';
		content += 'background:-moz-gradient(top, ' +  c1 + ' 50%, ' +  c2 + ' 100%);';
		content += 'background:-o-gradient(top, ' +  c1 + ' 50%, ' +  c2 + ' 100%);';
		content += ' height:100px; width:50px;"></td>';
	}
	content += '<td>' + MAX_PLUS_SUM.toFixed(2).replace(/\d(?=(\d{3})+\.)/g, '$&,')  + '</td>';
	content += '</tr>';
	content += '<tr>';
	content += '<td style="vertical-align:bottom;">' + MIN_PLUS_SUM.toFixed(2).replace(/\d(?=(\d{3})+\.)/g, '$&,')  + '</td>';
	content += '</tr>';
	if (MAX_MINUS_SUM < 0) {
		content += '<tr>';
		content += '<td style="height:45px;">' + MIN_MINUS_SUM.toFixed(2).replace(/\d(?=(\d{3})+\.)/g, '$&,')  + '</td>';
		content += '</tr>';
		content += '<tr>';		
		content += '<td style="height:25px;">' + MAX_MINUS_SUM.toFixed(2).replace(/\d(?=(\d{3})+\.)/g, '$&,') + '</td>';
		content += '</tr>';
	}
	content += '</table>';
	
	$('#legend-panel .panel-body').html(content);
}

// ----------------------------------------------------------------
//  Calculate fill color based on the amount of received money
// ----------------------------------------------------------------

/*
 * Calculate color of country representing the amount it received
 * (according to current options)
 */
function getCountryColor(id) {
    var amount = getIntervalAmount(id);
    	
	if (amount > 0) {
		if (_perCapita) {
			num = 255 - (Math.log(Math.abs(amount))) * 28;
		} else {
			num = 255 - (Math.log(Math.abs(amount)) - 14) * 28 + 50;
		}
		if (num > 200) {
			num = 200;
		}
		
		return toHex(13, num, 0);
		
	} else if (amount < 0) {
		if (_perCapita) {
			num = 255 - (Math.log(Math.abs(amount))) * 28;
		} else {
			num = 255 - (Math.log(Math.abs(amount)) - 14) * 28;
			//console.log(num);
			
		}	
		if (num > 200) {
			num = 200;
		}		
		
		return toHex(255, num, num);
	} else {
		return '#fff';
	}
}

// ----------------------------------------------------------------
//  Helpers
// ----------------------------------------------------------------

/* 
 * Limit x to be between 0 and 255
 */
function limit(x) {
	if (x > 255) return 255;
	if (x < 0) return 0;
	return Math.floor(x);
}

/*
 * Converts 3 integers representation of RGB color into single string
 * in which each color is represented by two hexadecimal digits
 */
function toHex(r, g, b) {
	r = limit(r);
	g = limit(g);
	b = limit(b);

	if (r > 15) r = r.toString(16);
	else r = '0' + r.toString(16);
	if (g > 15) g = g.toString(16);
	else g = '0' + g.toString(16);
	if (b > 15) b = b.toString(16);
	else b = '0' + b.toString(16);
	return '#' + (r + g + b).toUpperCase();
}

/*
 * Finds path element in svg map which belongs to given country
 */
function getPath(id) {
    var paths = map.getLayer("countryLayer").getPaths({"id":id});
    if (paths.length > 0) {
        return paths[0].svgPath;
    } else {
        return null;
    }
}

// ----------------------------------------------------------------
//  Map
// ----------------------------------------------------------------

/*
 * Country click event
 */
function countryClick(data, path, event) {
    selectCountry(data.id, path);
}

/*
 * Resizes map to fit current window width and height optimally
 */
function resizeMap() {
    // $holder.width($(window).width() - 20);
    map.resize();
    var aspectRatio = map.viewAB.height / map.viewAB.width;
    var mapHeight = map.viewBC.width * aspectRatio;
    if ($(window).width() >= SM_THRESHOLD) {
        mapHeight = Math.min(mapHeight, $holder.parent().height());
    };
    $holder.height(mapHeight);
    map.resize();
}

/*
 * Carries out all actions connected with selecting country
 * (map highlight and infobox update)
 */
function selectCountry(id, path) {
    if (!path) {
        path = getPath(id);
        if (!path) {
            return;
        }
    }

    //cleanHighlight();
	//colorMap();
	cleanStroke();
    if (id in countries) {
        //highlightCountry(id, path);
		strokeCountry(id, path);
        _countryId = id;
        updateInfobox(id);
    }
}


/*
 * Updates infobox according to current options and country selection.
 */
function updateInfobox(id) {
    if (id) {
        var name = countries[id]['name'];
        var title = name + '<i class="flag flag-' + id.toLowerCase() + '"/>';
        $('#country-panel .panel-title').html(title);
        redrawSidebar();
    }
}

// ----------------------------------------------------------------
//  Strokes
// ----------------------------------------------------------------

/*
 * Set all strokes to default style
 */
function cleanStroke() {
	for (p in map.pathById) {
		$(map.pathById[p].svgPath.node).attr('stroke', '#000')
		$(map.pathById[p].svgPath.node).attr('stroke-width', 1);
	}
}

/*
 * Set color of stroke of given country
 */
function strokeCountry(id, path, color) {
	var c = (color ? color : 'yellow');
	path.attr('stroke', c);
	path.attr('stroke-width', 2);
	path.toFront();
}

// ----------------------------------------------------------------
//  Highlighting
// ----------------------------------------------------------------

/*
 * Remove highlight
 */
function cleanHighlight() {
	for (p in map.pathById) {
		$(map.pathById[p].svgPath.node).attr('fill', '#eee')
	}
}

/*
 * Highlight country
 */
function highlightCountry(id, path, color) {
	var c = (color ? color : 'yellow');
	path.attr('fill', c);
}

// ----------------------------------------------------------------
//  Country search
// ----------------------------------------------------------------

/*
 * Perform country search
 */
function searchCountry(queryString) {
    var id = bestCountryMatch(queryString);
    selectCountry(id);
}


// ----------------------------------------------------------------
//  Sidebar
// ----------------------------------------------------------------

/*
 * Create time slider in the options panel
 */
function createTimeSlider() {
    timeSlider = $('#timeSliderTempl').slider()
    .on('slideStart', function(event) {
        movements = 0;
    })
    .on('slide', function(event) {
        movements += 1;
    })
    .on('slideStop', function(event) {
        var interval = timeSlider.getValue()['range'];
        var dragged = timeSlider.getValue()['dragged'];
        // click only -> select the clicked year instead of interaval
        if (movements < 5) {
            interval[1- dragged] = interval[dragged];
        }
        timeSlider.setValue(interval);
        changeTimeInterval(interval[0], interval[1]);
    })
    .data('slider');
    
    // adjust size and create tick marks
    resizeSlider();
}

/*
 * Resize slider
 */
function resizeSlider() {
    var minYear = timeSlider.min;
    var maxYear = timeSlider.max;
    var $slider = $("#timeSlider");
    var width = Math.min(180, $("#options-panel .panel-body").width()-10);
    var narrowSpace = Boolean(width < 130);
    $slider.css("width", width + "px");
    // tick marks
    var $sliderTrack = $slider.children(".slider-track");
    $sliderTrack.children(".tick-mark").remove();
    $sliderTrack.children(".tick-label").remove();
    var tickCount = maxYear - minYear + 1;
    for (var t=0; t < tickCount; t++) {
        var $tick = $('<div class="tick-mark"/>');
        $sliderTrack.append($tick);
        var year = (minYear + t).toString();
        if (narrowSpace) {
            year = year.slice(-2); // last two digits
        }
        var $label = $('<div class="tick-label">' + year + '</div>');
        $sliderTrack.append($label);
        var left = t * 100 / (tickCount-1); 
        $tick.css("left", left + "%");
        if (narrowSpace) {
            left += 3;
        }
        $label.css("left", left + "%");
    }
}

/*
 * Compute ideal width of graph with respect to the number of columns
 * in the graph and the width of country panel
 */
function idealGraphWidth() {
    if (_organization == 'TWB+UNDP') {
        var maxWidth = 40 * (3 + 2*(_interval[1] - _interval[0]));
    } else {
        var maxWidth = 45 * (2 + _interval[1] - _interval[0]);
        if (_interval[0] == _interval[1]) {
            maxWidth += 15;
        }
    }
    var width = $("#country-panel .panel-body").width();
    if (width > maxWidth) {
        width = maxWidth;
    }
    return width;
}

/*
 * Complete redraw of sidebar
 */
function redrawSidebar() {
    visualizeCountryData(_countryId);
    resizeSlider();
}


/*
 * Create summary string about aid for selected country
 */
function amountInfo(id) {
	content = '';
	if (_organization == 'TWB' || _organization == 'TWB+UNDP') {
		n = 0;
		for (var year = _interval[0]; year <= _interval[1]; year++) {
			n += getAmount(id, year, 'TWB');
		}
		n = n.toFixed(2).replace(/\d(?=(\d{3})+\.)/g, '$&,');
		content += '<p>World Bank summary: ' + n + '</p>';
	}
	if (_organization == 'UNDP' || _organization == 'TWB+UNDP') {
		n = 0;
		for (var year = _interval[0]; year <= _interval[1]; year++) {
			n += getAmount(id, year, 'UNDP');
		}
		n = n.toFixed(2).replace(/\d(?=(\d{3})+\.)/g, '$&,');
		content += '<p>UNDP summary: ' + n + '</p>';
	}
	return content;
}

// ----------------------------------------------------------------
//  Visualization of data about country
// ----------------------------------------------------------------

/*
 * Visualize data for selected country in country side panel
 */
function visualizeCountryData(id) {
    if (!id) {
        return;
    }

    if (!(id in _amounts)) {
        var content = 'No information about ' + countries[id]['name'] + '.';
        $('#country-panel .panel-body').html(content);
        return;
    }
	
    //var countryAmounts = _amounts[id];

    // check if there is a nonnegative amount
    var nonnegative = false;
    for (var year = _interval[0]; year <= _interval[1]; year++) {
        if (getAmount(id, year, 'TWB') > 0 && _organization != 'UNDP') {
            nonnegative = true;
        };
        if (getAmount(id, year, 'UNDP') > 0 && _organization != 'TWB') {
            nonnegative = true;
        };
    }
    if (!nonnegative) {
        $('#country-panel .panel-body').html('There are no nonnegative amounts.<br />' + amountInfo(id));
        return;
    }

    var width = idealGraphWidth();
    var intervalLength = _interval[1] - _interval[0] + 1;
    var narrowSpace = Boolean(intervalLength > 2 && 
            width < 88 + 27 * intervalLength);

    var content = '<canvas id="chart" width='+width+'px"></canvas>'
	content += amountInfo(id);
	
    if (!_perCapita) {
        content += '<p>Amounts in <strong>millions of USD</strong>.'
            + ' Only nonnegative amounts are shown.</p>'
    } else {
        content += '<p>Amounts in <strong>USD</strong>.'
            + ' Only nonnegative amounts are shown.</p>'
    }

    if (_organization == 'TWB+UNDP') {
        content += '<p><span class="square twbColor"/> World Bank</p>'
            + '<p><span class="square undpColor"/> UNDP</p>';
    }
    $('#country-panel .panel-body').html(content);

    var chartContext = $("#chart").get(0).getContext("2d");
    var chart = new Chart(chartContext);

    // create years value list and labels
    var labels = [];
    var valuesTWB = [];
    var  valuesUNDP = [];
    for (var year = _interval[0]; year <= _interval[1]; year++) {
        var label = year.toString();
        if (narrowSpace) {
            label = label.slice(-2); // last two digits
        }
        labels.push(label);
        valuesTWB.push(Math.max(0, getAmount(id, year, 'TWB')));
        valuesUNDP.push(Math.max(0, getAmount(id, year, 'UNDP')));
    }
    
    var datasets = [];
    if (_organization == 'TWB' || _organization == 'TWB+UNDP') {
        datasets.push({
            fillColor : "rgba(205,151,187,0.7)",
            stylerokeColor : "rgba(205,151,187,1)",
            data : valuesTWB
        });
    }
    if (_organization == 'UNDP' || _organization == 'TWB+UNDP') {
        datasets.push({
            fillColor : "rgba(187,205,151,0.7)",
            stylerokeColor : "rgba(187,205,151,1)",
            data : valuesUNDP
        });
    }

    // workarround to draw a single column chart
    if (intervalLength == 1 && _organization != 'TWB+UNDP') {
        datasets.push({
            fillColor : "rgba(255, 255, 255, 0)",
            stylerokeColor : "rgba(255, 255, 255, 0)",
            data : [0]
        });
    }

    var data = {
        labels : labels,
        datasets : datasets
    };
	
    var options = {};

    if (_perCapita) {
        options['scaleLabel'] = '<%=value%>'
    } else {
        options['scaleLabel'] = '<%=value/1000000%>'
    }
	
    chart.Bar(data, options);
	    
}
